//
// Created by kenny on 25-11-10.
//
// message.c
#include "mcp_msg_queue.h"
#include "../mcp_logger.h"
#include "../bm/sys_inc.h"

// memory_block 函数实现

memory_block* mb_create(unsigned int size) {
    memory_block* block = (memory_block*)XMALLOC(sizeof(memory_block));
    if (!block) return NULL;

    block->p_buff = NULL;
    block->buff_size = 0;
    block->buff_real_size = 0;

    if (size > 0) {
        block->p_buff = (unsigned char*)XMALLOC(size);
        if (!block->p_buff) {
            XFREE(block);
            return NULL;
        }
        block->buff_size = size;
    }

    return block;
}

memory_block* mb_copy(const memory_block* src) {
    if (!src) return NULL;

    memory_block* dest = mb_create(src->buff_size);
    if (!dest) return NULL;

    if (src->buff_real_size > 0 && src->p_buff) {
        memcpy(dest->p_buff, src->p_buff, src->buff_real_size);
        dest->buff_real_size = src->buff_real_size;
    }

    return dest;
}

void mb_destroy(memory_block* block) {
    if (!block) return;

    if (block->p_buff) {
        XFREE(block->p_buff);
        block->p_buff = NULL;
    }

    XFREE(block);
}

/**
 * 把 data 复制给 block
 * @param block
 * @param data
 * @param len
 * @return
 */
unsigned char* mb_copy_data(memory_block* block, const unsigned char* data, unsigned int len) {
    if (!block || !data || len == 0) {
        return NULL;
    }

    // 如果当前缓冲区大小不够，重新分配
    if (block->buff_size < len) {
        unsigned char* newBuff = (unsigned char*)realloc(block->p_buff, len);
        if (!newBuff) {
            return NULL;
        }
        block->p_buff = newBuff;
        block->buff_size = len;
    }

    memcpy(block->p_buff, data, len);
    block->buff_real_size = len;
    return block->p_buff;
}

/**
 * 把 data 加到 block 的后面
 * @param block
 * @param data
 * @param len
 * @return
 */
unsigned char* mb_add_copy_data(memory_block* block, const unsigned char* data, unsigned int len) {
    if (!block || !data) {
        return NULL;
    }

    if (len == 0) {
        return block->p_buff;
    }

    // 如果空间不够，重新分配
    unsigned int neededSize = block->buff_real_size + len;
    if (block->buff_size < neededSize) {
        unsigned char* newBuff = (unsigned char*)realloc(block->p_buff, neededSize);
        if (!newBuff) {
            return NULL;
        }
        block->p_buff = newBuff;
        block->buff_size = neededSize;
    }

    memcpy(block->p_buff + block->buff_real_size, data, len);
    block->buff_real_size = neededSize;
    return block->p_buff;
}

void mb_clear(memory_block* block) {
    if (!block || !block->p_buff) return;

    if (block->buff_size > 0) {
        memset(block->p_buff, 0, block->buff_size);
    }
    block->buff_real_size = 0;
}

unsigned int mb_get_buff_size(const memory_block* block) {
    return block ? block->buff_size : 0;
}

unsigned int mb_get_real_buff_size(const memory_block* block) {
    return block ? block->buff_real_size : 0;
}

unsigned char* mb_get_buff_head(const memory_block* block) {
    return block ? block->p_buff : NULL;
}

// message_queue_sh 函数实现

msg_queue* mq_create(void) {
    msg_queue* queue = (msg_queue*)XMALLOC(sizeof(msg_queue));
    if (!queue) return NULL;

    queue->used_size = 0;
    queue->unused_size = 0;
    queue->used_capacity = 10;
    queue->unused_capacity = 10;
    queue->total_blocks = 0;

    // 初始化队列数组
    queue->used_queue = (memory_block**)XMALLOC(sizeof(memory_block*) * queue->used_capacity);
    queue->unused_queue = (memory_block**)XMALLOC(sizeof(memory_block*) * queue->unused_capacity);

    if (!queue->used_queue || !queue->unused_queue) {
        if (queue->used_queue) XFREE(queue->used_queue);
        if (queue->unused_queue) XFREE(queue->unused_queue);
        XFREE(queue);
        return NULL;
    }

    // 初始化互斥锁 - 使用 sys_inc.h 中的函数
    queue->used_mutex = sys_os_create_mutex();
    queue->unused_mutex = sys_os_create_mutex();

    if (!queue->used_mutex || !queue->unused_mutex) {
        if (queue->used_mutex) sys_os_destroy_sig_mutex(queue->used_mutex);
        if (queue->unused_mutex) sys_os_destroy_sig_mutex(queue->unused_mutex);
        if (queue->used_queue) XFREE(queue->used_queue);
        if (queue->unused_queue) XFREE(queue->unused_queue);
        XFREE(queue);
        return NULL;
    }

    return queue;
}

void mq_destroy(msg_queue* queue) {
    if (!queue) return;

    // 销毁所有内存块
    sys_os_mutex_enter(queue->used_mutex);
    for (int i = 0; i < queue->used_size; i++) {
        if (queue->used_queue[i]) {
            mb_destroy(queue->used_queue[i]);
        }
    }
    XFREE(queue->used_queue);
    sys_os_mutex_leave(queue->used_mutex);

    sys_os_mutex_enter(queue->unused_mutex);
    for (int i = 0; i < queue->unused_size; i++) {
        if (queue->unused_queue[i]) {
            mb_destroy(queue->unused_queue[i]);
        }
    }
    XFREE(queue->unused_queue);
    sys_os_mutex_leave(queue->unused_mutex);

    sys_os_destroy_sig_mutex(queue->used_mutex);
    sys_os_destroy_sig_mutex(queue->unused_mutex);

    XFREE(queue);
}

int mq_get_msg_size_que_used(const msg_queue* queue) {
    if (!queue) return 0;

    sys_os_mutex_enter((void*)queue->used_mutex);
    int size = queue->used_size;
    sys_os_mutex_leave((void*)queue->used_mutex);

    return size;
}

int mq_get_msg_size_que_unused(const msg_queue* queue) {
    if (!queue) return 0;

    sys_os_mutex_enter((void*)queue->unused_mutex);
    int size = queue->unused_size;
    sys_os_mutex_leave((void*)queue->unused_mutex);

    return size;
}

/**
 * 未使用，如果有则取最后一个，没有则加一个新的，超出容易则返回空的
 * @param queue
 * @return
 */
memory_block* mq_get_msg_que_unuse(msg_queue* queue) {
    if (!queue) return NULL;

    memory_block* msg = NULL;

    sys_os_mutex_enter(queue->unused_mutex);

    if (queue->unused_size > 0) {
        msg = queue->unused_queue[queue->unused_size - 1];
        queue->unused_size--;
    } else {
        if (queue->total_blocks > MAX_MEM_NUM) {
            LOG_ERROR("Message Unuse too long, something wrong. used:%d total_blocks:%lu unuse:%d\n",
                   queue->used_size, queue->total_blocks, queue->unused_size);
            sys_os_mutex_leave(queue->unused_mutex);
            return NULL;
        }

        msg = mb_create(MAX_MSG_LEN);
        if (msg) {
            queue->total_blocks++;
        }
    }

    sys_os_mutex_leave(queue->unused_mutex);
    return msg;
}

/**
 * 已使用的，有则取最后一个，否则返回空的
 * @param queue
 * @return
 */
memory_block* mq_get_msg_que_used(msg_queue* queue) {
    if (!queue) return NULL;

    memory_block* msg = NULL;

    sys_os_mutex_enter(queue->used_mutex);

    if (queue->used_size > 0) {
        msg = queue->used_queue[queue->used_size - 1];
        queue->used_size--;
    }

    sys_os_mutex_leave(queue->used_mutex);
    return msg;
}

/**
 * 提交未使用块，返回0 成功
 * @param queue
 * @param msg
 * @return
 */
int mq_submit_msg_que_unuse(msg_queue* queue, memory_block* msg) {
    if (!queue || !msg) {
        LOG_DEBUG("!mq_submit_msg_que_unuse() failed: queue or msg is NULL\n");
        return -1;
    }

    sys_os_mutex_enter(queue->unused_mutex);

    // 检查是否需要扩容
    if (queue->unused_size >= queue->unused_capacity) {
        int newCapacity = queue->unused_capacity * 2;
        if (!resize_queue(&queue->unused_queue, &queue->unused_capacity, newCapacity)) {
            sys_os_mutex_leave(queue->unused_mutex);
            return -1;
        }
    }

    queue->unused_queue[queue->unused_size] = msg;
    queue->unused_size++;

    sys_os_mutex_leave(queue->unused_mutex);
    return 0;
}

/**
 * 提交已使用块
 * @param queue
 * @param msg
 * @return
 */
int mq_submit_msg_que_used(msg_queue* queue, memory_block* msg) {
    if (!queue || !msg) {
        printf("!mq_submit_msg_que_used() failed: queue or msg is NULL\n");
        return -1;
    }

    sys_os_mutex_enter(queue->used_mutex);

    // 检查是否需要扩容
    if (queue->used_size >= queue->used_capacity) {
        int newCapacity = queue->used_capacity * 2;
        if (!resize_queue(&queue->used_queue, &queue->used_capacity, newCapacity)) {
            sys_os_mutex_leave(queue->used_mutex);
            return -1;
        }
    }

    queue->used_queue[queue->used_size] = msg;
    queue->used_size++;

    sys_os_mutex_leave(queue->used_mutex);
    return 0;
}

// 辅助函数：调整队列大小
static int resize_queue(memory_block*** queue, int* capacity, int newCapacity) {
    memory_block** newQueue = (memory_block**)realloc(*queue, sizeof(memory_block*) * newCapacity);
    if (!newQueue) {
        return 0;
    }

    *queue = newQueue;
    *capacity = newCapacity;
    return 1;
}